define(function (require, exports, module) {
   // require("./IBA_AnnotHandler.js");
    require("../../ImageEngine/AnnotUIManager.js");
    var CommonTools = WebPDF.Common;
    var PDFPoint = WebPDF.PDFPoint;
    var PDFRect = WebPDF.PDFRect;
    var RectUtils = WebPDF.RectUtils;

    require("./MarkupAnnotHandler.js");
    require("../../PDFData/TypewriterAnnot.js")
    var CommentAnnotHandler = require("./CommentAnnotHandler.js");
    var CommonMarkupAnnotHandler = require("./CommonMarkupAnnotHandler.js");
    var LinkAnnotHandler = require("./LinkAnnotHandler.js");
    var TextAnnotHandler = require("./TextAnnotHandler.js");
    var TypewriterAnnotHandler = require("./TypewriterAnnotHandler.js");
    var DrawingAnnotHandler = require("./DrawingAnnotHandler.js");


    WebPDF.AnnotHandleManager = function (readerApp, baseAnnotPlugin) {
        var _readerApp = readerApp,
            /**
             * Map for annot handler
             * @type {{String : WebPDF.IBA_AnnotHandler}}
             * @private
             */
            _annotHandlerMap = {},
            _baseAnnotPlugin = baseAnnotPlugin,
            _annotSelectedList = {},
            _focusAnnot = null,
            _selectAnnotPageView = null,
            _annotMenuContainerID = "fwr-annots-context-menu-container",
            _annotMenuID = "fwr-annots-context-menu",
            _markUpAnnotHandler = null,
            _self = this;

        var _bLButtonMouseDown = false;
        var _oldMousePtX = 0;
        var _oldMousePtY = 0;
        /**
         * 存储已经创建annotation的页面列表
         * @type {{Number : Boolean}}
         * @private
         */
        var _pageAnnotCreatedList = {};
        /**
         * 存储已经更新annotation位置信息的页面列表
         * @type {Array.<Boolean>}
         * @private
         */
        var _pageAnnotUpdatedList = [];
        /**
         * 存储需要更新annotation位置的页面列表
         * @type {Array.<Number>}
         * @private
         */
        var _pageAnnotNeedUpdateList = [];

        var docView = _readerApp.getMainView().getDocView();
         var _annotCanvasID = docView.getDocViewContainerID() + "_AnnotCanvas";
        var _annotUIManager = new WebPDF.ImageEngine.AnnotUIManager(this, _readerApp);
        var  menuPlugin = _readerApp.getPluginByName(WebPDF.CONTEXTMENU_PLUGIN_NAME);
        
        function _createAnnotMenu() {
            var menuHtml = "<div id='" + _annotMenuContainerID + "'><ul id='" + _annotMenuID
                + "' class='fwrContextMenu fwr_cm_default' style='display: none;' fxmouse='false'></div>";
            _readerApp.getMainView().$el.after(menuHtml);            
            
            _createCmdAndMenuItem();               
            
            var menuItemsHtml = "";
            var menuBar = WebPDF.Config.MenuBar;                     
            var menuItems = menuBar['annot'].items;
            for (var k = 0; k < menuItems.length; k++) {
                var menuItem = menuItems[k];
                if (menuItem.enable){
                    menuItemsHtml += menuPlugin.createMenuItemHtml(menuItems[k]);
                }
            }                    
            
            $("#" + _annotMenuID).append(menuItemsHtml);
        }
        
         /**
         * Create menus
         * @private
         */
        function _createCmdAndMenuItem() {         
            _readerApp.addMenuItem({
                name: "MenuAnnotCut",
                createHtml: function () {
                    return "<li class='icon' menuname='MenuAnnotCut'><span class='cut icon'>Cut</span></li>";
                },
                onShow: function (jqMenuItem) {       
                     jqMenuItem.addClass('disabled');   
                },
                onSelect: function (jqMenuItem) {                   
                }
            });
            _readerApp.addMenuItem({
                name: "MenuAnnotCopy",
                createHtml: function () {
                    return "<li class='icon' menuname='MenuAnnotCopy'><span class='copy icon'>Copy</span></li>";
                },
                onShow: function (jqMenuItem) {      
                     jqMenuItem.addClass('disabled');   
                },
                onSelect: function (jqMenuItem) {                    
                }
            });
            _readerApp.addMenuItem({
                name: "MenuAnnotPaste",
                createHtml: function () {
                    return "<li class='icon' menuname='MenuAnnotPaste'><span class='paste icon'>Paste</span></li>";
                },
                onShow: function (jqMenuItem) {     
                     jqMenuItem.addClass('disabled');   
                },
                onSelect: function (jqMenuItem) {                   
                }
            });
            _readerApp.addMenuItem({
                name: "MenuAnnotDelete",
                createHtml: function () {
                    return "<li class='icon' menuname='MenuAnnotDelete'><span class='delete icon'>Delete</span></li>";
                },
                onShow: function (jqMenu) {                           
                },
                onSelect: function (jqMenuItem) {                       
                     _self.deleteSelection();
                    return true;
                }
            });
            _readerApp.addMenuItem({
                name: "MenuAnnotOpenPopupNote",
                createHtml: function () {
                    return "<li class='icon' menuname='MenuAnnotOpenPopupNote'><span class='icon'>Open Popup Note</span></li>";
                },
                onShow: function (jqMenuItem) {    
                    jqMenuItem.addClass('disabled');                    
                },
                onSelect: function (jqMenuItem) {                   
                }
            });
            _readerApp.addMenuItem({
                name: "MenuAnnoOpenAllPopups",
                createHtml: function () {
                    return "<li class='icon' menuname='MenuAnnoOpenAllPopups'><span class='icon'>Open All Popups</span></li>";
                },
                onShow: function (jqMenuItem) {         
                   jqMenuItem.addClass('disabled');   
                },
                onSelect: function (jqMenuItem) {                  
                }
            });

            _readerApp.addMenuItem({
                name: "MenuAnnotCloseAllPopups",
                createHtml: function () {
                    return "<li  class='icon' menuname='MenuAnnotCloseAllPopups'><span class='icon'>Close All Popups</span></li>";
                },
                onShow: function (jqMenuItem) {    
                    jqMenuItem.addClass('disabled');   
                },
                onSelect: function (jqMenuItem) {                   
                }
            });           
        }    
        
       

        this.init = function () {
            _resetAnnotUpdatedList();
            _annotUIManager.init();
            var annotHandler = null;

            annotHandler = new CommentAnnotHandler(_readerApp, _self, WebPDF.PDFData.CommentAnnotType.COMMENTTYPE_UNDERLINE);
            _self.registerAnnotHandler(annotHandler);
            
            annotHandler = new CommentAnnotHandler(_readerApp, _self, WebPDF.PDFData.CommentAnnotType.COMMENTTYPE_HIGHLIGHT);
            _self.registerAnnotHandler(annotHandler);

            annotHandler =new CommonMarkupAnnotHandler(_readerApp, _self, WebPDF.CommonMarkupHandler);
            _self.registerAnnotHandler(annotHandler);
            
            annotHandler =new DrawingAnnotHandler(_readerApp, _self, WebPDF.InkHandler);
            _self.registerAnnotHandler(annotHandler);

            annotHandler = new LinkAnnotHandler(_readerApp);
            _self.registerAnnotHandler(annotHandler);

            annotHandler = new TextAnnotHandler(_readerApp,_self);
            _self.registerAnnotHandler(annotHandler);

            annotHandler = new TypewriterAnnotHandler(_readerApp , WebPDF.PDFData.TypewriterAnnotType.TYPEWRITERTYPE_TYPEWRITER,_self);
            _self.registerAnnotHandler(annotHandler);
            
            _markUpAnnotHandler = new WebPDF.MarkupAnnotHandler(_readerApp, _self);
            _markUpAnnotHandler.init();
            _self.bindAnnotEvents();
            _createAnnotMenu();
         
        };

        this.getMarkupAnnotHandler = function(){
            return _markUpAnnotHandler;
        };

        this.getContextMenuId = function(){
            return _annotMenuID;
        };

        function _resetAnnotUpdatedList () {
            var iCnt = _readerApp.getMainView().getDocView().getPDFDoc().getPageCount();
            for (var i = 0; i < iCnt; i++) {
                _pageAnnotUpdatedList[i] = false;
            }
        }

        /**
         * 判断对应页面的annotation是否已经创建
         * @param pageIndex
         * @returns {*}
         */
        this.isPageAnnotCreated = function (pageIndex) {
            return _pageAnnotCreatedList[pageIndex];
        };

        this.onDocViewZoom = function(scale) {
            _resetAnnotUpdatedList();
            var docView = _readerApp.getMainView().getDocView();
            var visiblePageRange = docView.getVisiblePageRange();
            var jqPagesContainerDiv = $("#" + docView.getDocViewContainerID());
            var docViewDimension = docView.getDocViewDimension();
            var contentPanelHeight = docViewDimension.height;
            var contentPanelWidth = docViewDimension.width;
            var contentPanelOffset = jqPagesContainerDiv.offset();
            for (var i = visiblePageRange.begin; i <= visiblePageRange.end; i++) {
                _self.onPageVisible(docView.getPageView(i), contentPanelWidth, contentPanelHeight, contentPanelOffset, true);
            }
            for (var key in _pageAnnotNeedUpdateList) {
                var pageIndex = _pageAnnotNeedUpdateList[key];
                if (_pageAnnotUpdatedList[pageIndex] === false) {
                    _self.onPageVisible(docView.getPageView(pageIndex), contentPanelWidth, contentPanelHeight,
                        contentPanelOffset, true);
                }
            }
            _pageAnnotNeedUpdateList.length = 0;
        };

        this.onPageVisible = function(pageView, contentPanelWidth, contentPanelHeight, contentPanelOffset) {
            if (!pageView || pageView.isPageLoadError()) {
                return false;
            }
            var pageIndex = pageView.getPageIndex();
            if(!_pageAnnotCreatedList[pageIndex]){
                return false;
            }
            if (_pageAnnotUpdatedList[pageIndex]){
                _self.showAnnots(pageView, true);
               return false;
            }

            var annotVisibleRect = _self.getAnnotVisibleRect(pageView, contentPanelOffset, contentPanelWidth,
                contentPanelHeight);
            _self.updateAnnotsPosition(pageView, annotVisibleRect);
            _pageAnnotUpdatedList[pageIndex] = true;
            _self.showAnnots(pageView, true);
            return true;
        };

        this.onPageShowComplete = function(pageView) {            
           
            if (!pageView || pageView.isPageLoadError()){
                return false;
            }            
            if (!pageView.getPDFPage().getAnnotJsonData()) return false; 
            
            var pageIndex = pageView.getPageIndex();
            if (!_pageAnnotCreatedList[pageIndex]) {
                var annotHtml = _self.createAnnotsHtmlContent(pageView);            
              
                $("#" + pageView.getPageViewContainerID()).append(annotHtml);
                _self.drawAnnots(pageView, false);
                _pageAnnotCreatedList[pageIndex] = true;
                //_annotHandlerMgr.bindPopupContextmenuEvent();
            }
            var docView = _readerApp.getMainView().getDocView();
            var jqPagesContainerDiv = $("#" + docView.getDocViewContainerID());
            var docViewDimension = docView.getDocViewDimension();
            var contentPanelHeight = docViewDimension.height;
            var contentPanelWidth = docViewDimension.width;
            var contentPanelOffset = jqPagesContainerDiv.offset();
            _self.onPageVisible(pageView, contentPanelWidth, contentPanelHeight, contentPanelOffset);
            return true;
        };

        this.onPageInvisible = function(pageView) {
            _self.showAnnots(pageView, false);
            return true;
        };

        /**
         * Register an annotation handler
         * @param {WebPDF.IBA_AnnotHandler} annotHandler
         */
        this.registerAnnotHandler = function (annotHandler) {
            if (annotHandler == null) return;
            var type = annotHandler.getType();
            try {
                if (_annotHandlerMap[type] != null)
                    $.error("The annotation handler '" + type + "' has already been registered!");
                _annotHandlerMap[type] = annotHandler;
            }
            catch (ex) {
                console.error(ex);
            }
        };
        /**
         * Get annot handler by type.
         * @param annotHandlerType type of annot handler
         * @returns {WebPDF.IBA_AnnotHandler}
         */
        this.getAnnotHandler = function (annotHandlerType) {
            return _annotHandlerMap[annotHandlerType];
        };

        /**
         * Get annot handler by annot.
         * @param {WebPDF.PDFAnnot} annot
         * @returns {WebPDF.IBA_AnnotHandler}
         */
        this.getAnnotHandlerByAnnot = function (annot) {
            var annotType = annot.getType();
            switch (annotType) {
                case WebPDF.PDFData.AnnotType.MarkUp:
                {
                    var headAnnot = annot.getHeadAnnot();
                    if (headAnnot != null) {
                        return _self.getAnnotHandler(headAnnot.getSubType());
                    }
                    else {
                        return _self.getAnnotHandler(annot.getSubType());
                    }
                }
                    break;
                case WebPDF.PDFData.AnnotType.TypeWriter:
                {
                    return _self.getAnnotHandler(annot.getIT());
                }
                    break;
                default:
                    return null;
            }
        };

        /**
         * Check whether an annotation can be handle
         * @param annot the annotation to check
         * @param bAllowSelectTextTool
         * @returns {WebPDF.IBA_AnnotHandler} return null if the annotation can not be handle,
         * otherwise return the handler of current annotation.
         */
        this.canAnswer = function (annot, bAllowSelectTextTool) {
            var annotType = annot.getType();
            switch (annotType) {
                case WebPDF.PDFData.AnnotType.MarkUp:
                {
                    if (annot.isVisible()) {
                        var headAnnot = annot.getHeadAnnot();
                        if (headAnnot != null) {
                            var headerAnnotHandler = _self.getAnnotHandler(headAnnot.getSubType());
                            if(headerAnnotHandler == null){
                                headerAnnotHandler = _self.getAnnotHandler(WebPDF.CommonMarkupHandler);
                            }
                            if (headerAnnotHandler != null) {
                                return headerAnnotHandler.canAnswer(headAnnot, bAllowSelectTextTool) ? headerAnnotHandler : null;
                            }
                            else {
                                return null;
                            }
                        }
                        else {
                            var annotHandler = _self.getAnnotHandler(annot.getSubType());
                            if(annotHandler == null){
                                annotHandler = _self.getAnnotHandler(WebPDF.CommonMarkupHandler);
                            }
                            if (annotHandler != null) {
                                return annotHandler.canAnswer(annot, bAllowSelectTextTool) ? annotHandler : null;
                            }
                            else {
                                return null;
                            }
                        }
                    }
                }
                    break;
                case WebPDF.PDFData.AnnotType.TypeWriter:
                {
                    var annotHandler = _self.getAnnotHandler(annot.getIT());
                    if (annotHandler != null) {
                        return annotHandler.canAnswer(annot, bAllowSelectTextTool) ? annotHandler : null;
                    }
                    else {
                        return null;
                    }
                }
                    break;
                case WebPDF.PDFData.AnnotType.Link:{
                    var annotHandler = _self.getAnnotHandler("Link");
                    if (annotHandler != null) {
                        return annotHandler.canAnswer(annot, bAllowSelectTextTool) ? annotHandler : null;
                    }
                    else {
                        return null;
                    }
                }break;
                default:
                    return null;
            }
        };

        /**
         * Clear all selection of annotations.
         */
        this.clearSelection = function () {
           // $('.fwr-annot-selected').nojeegoocontext();
            for (var key in _annotSelectedList) {
                var annot = _annotSelectedList[key];
                var annotHandler = _self.getAnnotHandlerByAnnot(annot);
                annotHandler && annotHandler.onDeSelected(_selectAnnotPageView, annot);
            }
            _annotSelectedList = {};
            _focusAnnot = null;
            _selectAnnotPageView = null;
        };

        /**
         * Set focus annotation
         * @param pageView
         * @param annot
         * @ignore
         */
        this.setFocusAnnot = function (pageView, annot) {
            _focusAnnot = annot;
            _selectAnnotPageView = pageView;
            if (annot.getType() === WebPDF.PDFData.AnnotType.MarkUp) {
                if (annot.getHeadAnnot() != null) {
                    _focusAnnot = annot.getHeadAnnot();
                }
            }
            var annotHandler = _self.getAnnotHandlerByAnnot(_focusAnnot);
            annotHandler && annotHandler.onFocus(pageView, annot);
        };


        this.addSelection = function (annot) {             
            var annotName = annot.getAnnotName();
            _annotSelectedList[annotName] = annot;
            var annotHandler = _self.getAnnotHandlerByAnnot(annot);
            if(annotHandler && annotHandler.onSelected(_selectAnnotPageView, annot))
            {
                $(".fwr-annot-selected").fwrContextMenu(_annotMenuID, {
                    onSelect: function (e, context) { 
                        menuPlugin.onSelect($(this)); 
                    },
                    onShow: function(e, context){                       
                        menuPlugin.onShow($(this)); 
                    }                  
                },document.getElementById(_readerApp.getMainView().getMainFrameID()));
            }
        }; 

        this.selectAnnot = function (pageView, annot) {
            if (annot.getType() === WebPDF.PDFData.AnnotType.MarkUp) {
                var header = annot.getHeadAnnot();
                if (header != null) {
                    _self.addSelection(header);
                    var annotGroup = header.getGroupAnnotMap();
                    for (var key in annotGroup) {
                        var childAnnot = annotGroup[key];
                        _self.addSelection(childAnnot);
                    }
                }
                else
                    _self.addSelection(annot);
            }
            else {
                _self.addSelection(annot);
            }
        };

        this.selectAnnotsByRect = function (pageView, pdfRect) {
            var bFirst = true;
            var pdfPage = pageView.getPDFPage();
            pdfPage.enumAnnots(function (annot) {
                var annotHandler = _self.canAnswer(annot);
                if (annotHandler != null) {
                    var annotPDFRect = annot.getRect();
                    RectUtils.intersect(annotPDFRect, pdfRect);
                    if (!RectUtils.isEmpty(annotPDFRect)) {
                        if (bFirst) {
                            _self.setFocusAnnot(pageView, annot);
                            bFirst = false;
                        }
                        _self.selectAnnot(pageView, annot);
                    }
                }
                return true;
            });
        };

        this.clickOnAnnot = function (annot, pageView, bContinueSelect) {
            if (pageView != _selectAnnotPageView) {
                _self.clearSelection();
            }
            document.getElementById(pageView.getDocView().getDocViewContainerID()).focus();
            if (!_focusAnnot) {
                _self.setFocusAnnot(pageView, annot);
                _self.selectAnnot(pageView, annot);
            }
            else {
                if (_annotSelectedList[annot.getAnnotName()] != null) {
                    return;
                }
                else {
                    if (!bContinueSelect) {
                        _self.clearSelection();
                        _self.setFocusAnnot(pageView, annot);
                        _self.selectAnnot(pageView, annot);
                    }
                    else {
                        _self.addSelection(annot);
                    }
                }
            }
        };

        this.onAnnotLButtonDown = function (pageView, annot, event) {              
            if (annot != null) {
                var annotHandler = _self.canAnswer(annot);
                if (!annotHandler) {
                    return false;
                }
                if (annotHandler.onLButtonDown(pageView, annot, event)) {
                    var bShift = event.shiftKey;
                    var bCtrl = event.ctrlKey;
                    var bContinueSelect = true;
                    if (!bShift && !bCtrl)
                        bContinueSelect = false;
                    _self.clickOnAnnot(annot, pageView, bContinueSelect);
                }                
                
               // if (!annotHandler.canMove(annot.getSubType())) {
                 //   return false;
               // }
                $(".fwr-annot-move-div").remove();               
                _oldMousePtY = event.pageY; //当前鼠标位置
                _oldMousePtX = event.pageX; //当前鼠标位置
                WebPDF.Common.preventDefaults(event, true);
                _bLButtonMouseDown = true;               
                return true;
            }
            else {
            	if(event.target.getAttribute("menuname")!=null){
            		return false;
            	};                                
                _self.clearSelection();
            }
            return false;
        };

        /**
         * 判断选中的annotation能否被移动
         * @private
         * @returns {Boolean} 如果可以移动返回true， 否则返回false
         */
        this._isSelectionCanMove = function () {
            if (!_readerApp.isEditable()) {
                return false;
            }
            var annotHandler;
            for (var key in _annotSelectedList) {
                var annot = _annotSelectedList[key];
                annotHandler = _self.getAnnotHandler(annot.getSubType());
                if (annotHandler){
                    if(!annotHandler.canMove(annot.getSubType())) {
                        return false;
                    }
                }else {
                    return false;
                }
            }
            return true;
        };

        /**
         * 根据页面位置重新校正鼠标移动的偏移量
         * @param pageView 当前页面
         * @param curMousePageX 当前鼠标x轴位置
         * @param curMousePageY 当前鼠标y轴位置
         * @returns {{x: number, y: number}}
         * @private
         */
        function _getAnnotVisibleOffset(pageView, curMousePageX, curMousePageY) {
            var pageViewHeight = pageView.getPageViewHeight();
            var pageViewWidth = pageView.getPageViewWidth();
            var offsetX = curMousePageX - _oldMousePtX;
            var offsetY = curMousePageY - _oldMousePtY;
            var selectedAnnotsRect = new PDFRect();
            var bFirst = true;
            var moveElem, annot, annotRect, annotMoveDivID, annotDocRect = new PDFRect();
            for (var key in _annotSelectedList) {
                annot = _annotSelectedList[key];
                annotMoveDivID = _annotUIManager.getAnnotMoveDivID(pageView, key);
                moveElem = document.getElementById(annotMoveDivID);
                if (moveElem) {
                    var jqMoveElem = $(moveElem);
                    annotDocRect.bottom = parseFloat(jqMoveElem.css("top"));
                    annotDocRect.left = parseFloat(jqMoveElem.css("left"));
                    annotDocRect.top = annotDocRect.bottom + parseFloat(jqMoveElem.css("height"));
                    annotDocRect.right = annotDocRect.left + parseFloat(jqMoveElem.css("width"));
                } else {
                    annotRect = annot.getRect();
                    annotDocRect = pageView.pdfToDoc(annotRect, true);
                }
                bFirst ? RectUtils.copy(annotDocRect, selectedAnnotsRect) : RectUtils.union(selectedAnnotsRect, annotDocRect);
                bFirst = false;
            }

            if (offsetX > 0) {
                var curRight = selectedAnnotsRect.right + offsetX;
                if (curRight > pageViewWidth) {
                    offsetX = pageViewWidth - selectedAnnotsRect.right;
                }
            } else {
                var curLeft = selectedAnnotsRect.left + offsetX;
                if (curLeft < 0) {
                    offsetX = 0 - selectedAnnotsRect.left;
                }
            }

            if (offsetY > 0) {
                var curTop = selectedAnnotsRect.top + offsetY;
                if (curTop > pageViewHeight) {
                    offsetY = pageViewHeight - selectedAnnotsRect.top;
                }
            } else {
                var curTop = selectedAnnotsRect.bottom + offsetY;
                if (curTop < 0) {
                    offsetY = 0 - selectedAnnotsRect.bottom;
                }
            }

            var pageOffsetHtmlDoc = $("#" + pageView.getPageViewContainerID()).offset();
            var pageViewRect = new PDFRect(pageOffsetHtmlDoc.left, pageOffsetHtmlDoc.top,
                    pageOffsetHtmlDoc.left + pageViewWidth, pageOffsetHtmlDoc.top + pageViewHeight);
            if (((offsetX > 0) && (curMousePageX < pageViewRect.left)) || ((offsetX < 0) && (curMousePageX > pageViewRect.right))) {
                offsetX = 0;
            }

            if (((offsetY > 0) && (curMousePageY < pageViewRect.top)) || ((offsetY < 0) && (curMousePageY > pageViewRect.bottom))) {
                offsetY = 0;
            }
            return { x: offsetX, y: offsetY };
        }

        this.onAnnotMouseMove = function (pageView, annot, event) {          
            if (_bLButtonMouseDown) {                
                 for (var key in _annotSelectedList) {                   
                    var handler = _self.getAnnotHandlerByAnnot(_annotSelectedList[key]);
                     if (handler && handler.onMouseMove) handler.onMouseMove(_annotSelectedList[key], event);
                 }  
              
                if (_self._isSelectionCanMove()) {
                    var offset = _getAnnotVisibleOffset(_selectAnnotPageView, event.pageX, event.pageY);
                 //   var jqPageAnnot = _annotUIManager.getPageAnnotsContainerID(_selectAnnotPageView);

                    var moveElem, selectedAnnot, annotRect, annotMoveDivID, annotDocRect = new PDFRect();
                    for (var key in _annotSelectedList) {
                        selectedAnnot = _annotSelectedList[key];
                        var jqPageAnnot = $("#" + _annotUIManager.getAnnotDivID(_selectAnnotPageView, key));
                        annotMoveDivID = _annotUIManager.getAnnotMoveDivID(_selectAnnotPageView, key);
                        moveElem = document.getElementById(annotMoveDivID);
                        if (moveElem) {
                            var jqMoveElem = $(moveElem);
                            jqMoveElem.css("left", (parseFloat(jqMoveElem.css("left")) + offset.x) + "px")
                                .css("top", (parseFloat(jqMoveElem.css("top")) + offset.y) + "px");
                        } else {
                            annotRect = selectedAnnot.getRect();
                            annotDocRect = _selectAnnotPageView.pdfToDoc(annotRect, true);
                            var style = {
                                "left" : (parseFloat(jqPageAnnot.css("left")) + offset.x) + "px",                                         
                                "top" :(parseFloat(jqPageAnnot.css("top")) + offset.y) + "px",
                                "width": jqPageAnnot.css("width"),
                                "height": jqPageAnnot.css("height"),
                                "position": "absolute",
                                "background-color": "white",
                                "opacity": ".8"
                            }                        
                                    
                            var annotMoveDivHtml = $("<div></div>").css(style).attr("id", annotMoveDivID).addClass("fwr-annot-move-div");        
                            jqPageAnnot.after(annotMoveDivHtml);
                        }
                    }
                }
                _oldMousePtY = event.pageY; //当前鼠标位置
                _oldMousePtX = event.pageX; //当前鼠标位置
            }
            return false;
        };

        this.onAnnotLButtonUp = function (pageView, annot, event) {          
            if (_bLButtonMouseDown) {
                var docView = _selectAnnotPageView.getDocView();
                var pt2Pixel = _readerApp.getPixelsPerPoint();
                var scale = _selectAnnotPageView.getScale() * pt2Pixel;
                var timestamp = (new Date()).valueOf().toString();
                var selectedAnnot, annotMoveDivID, moveElem, annotPDFRect, annotDocRect, offsetX, offsetY
                    , jqMoveElem, annotHandler, offsetInPDFX, offsetInPDFY, newPosX, newPosY;               
             
                for (var key in _annotSelectedList) {
                    selectedAnnot = _annotSelectedList[key];
                     //                selectedAnnot.getPage();
                    annotHandler = _self.getAnnotHandlerByAnnot(selectedAnnot);
                    if (annotHandler && annotHandler.onLButtonUp) annotHandler.onLButtonUp(selectedAnnot, _selectAnnotPageView, event);
                    if (!annotHandler) continue;
                    annotMoveDivID = _annotUIManager.getAnnotMoveDivID(_selectAnnotPageView, key);
                    moveElem = document.getElementById(annotMoveDivID);
                    if (!moveElem) continue;
                    jqMoveElem = $(moveElem);
                    annotPDFRect = selectedAnnot.getRect();
                    annotDocRect = _selectAnnotPageView.pdfToDoc(annotPDFRect, true);
                    newPosX = parseFloat(jqMoveElem.css("left"));
                    newPosY = parseFloat(jqMoveElem.css("top"));
                    offsetX = newPosX - annotDocRect.left;
                    offsetY = newPosY - annotDocRect.top;

                    annotDocRect.left = newPosX;
                    annotDocRect.top = newPosY;
                    annotDocRect.right =  annotDocRect.right + offsetX;
                    annotDocRect.bottom =  annotDocRect.bottom + offsetY
                    annotPDFRect =  _selectAnnotPageView.docToPDF(annotDocRect,true);
//                    offsetInPDFX = offsetX / scale;
//                    offsetInPDFY = -offsetX / scale;
//                    RectUtils.offset(annotDocRect, offsetInPDFX, offsetInPDFY);                   
                    selectedAnnot.setRect(annotPDFRect);
                    annotHandler.moveAnnot(_selectAnnotPageView, selectedAnnot,
                        offsetX, offsetY, newPosX, newPosY);

                    selectedAnnot.setModifyDate(timestamp);
                    _readerApp.setModified(_selectAnnotPageView, docView, true);
                }
                $(".fwr-annot-move-div").remove();
            }
            _bLButtonMouseDown = false;
            return false;
        };


        this.deleteSelection = function () {
            var isModified = false;
            var annotDeletedMap = {};
            //首先隐藏已弹出的菜单栏
            $('.fwr-annot-selected').hidden();
            var annotHandler;
            for (var key in _annotSelectedList) {
                var annot = _annotSelectedList[key];
                if (annot) {
                    if (annotHandler = _self.getAnnotHandlerByAnnot(annot)) {
                        annotHandler.deleteAnnot(_selectAnnotPageView, annot, _annotUIManager);
                        if (annot.isSourceAnnot) {
                            annot.hide();
                        }
                        else {
                            annotDeletedMap[key] = 1;
                        }
                        isModified = true;
                    }
                }
            }
            if (isModified) {
                _selectAnnotPageView.getPDFPage().deleteAnnots(annotDeletedMap);
                _readerApp.setModified(_selectAnnotPageView, _selectAnnotPageView.getDocView(), true);
            }
            _self.clearSelection();
            _self.onDraw();
        };

        this.onAnnotLButtonDblClk = function (pageView, annot, event) {
            if (annot != null) {
                var annotHandler = _self.canAnswer(annot);
                if (!annotHandler) {
                    return false;
                }
                annotHandler.onLButtonDblClk(pageView, annot, event);
                return true;
            }
            return false;
        };

        this.onAnnotMouseOver = function (pageView, annot, event) {
            if (!annot)
                return false;
            try {
                var pageIndex = pageView.getPageIndex();
                var annotName = annot.getAnnotName();
                var annotHandler = _self.canAnswer(annot);
                if (annotHandler == null) {
                    return false;
                }
                annotHandler.onMouseOver(pageView, annot, event);
                return true;
            }
            catch (ex) {
                console.error(ex);
                return false;
            }
        };

        this.onAnnotMouseLeave = function (pageView, annot, event) {
            if (!annot)
                return false;
            try {
                var annotHandler = _self.canAnswer(annot);
                if (annotHandler == null){
                    return false;
                }
                annotHandler.onMouseLeave(pageView, annot, event);
                return true;
            }
            catch (ex) {
                console.error(ex);
                return false;
            }
        };

        this.updateAnnotsPosition = function (pageView, visibleRect) {
            var pdfPage = pageView.getPDFPage();
            pdfPage.enumAnnots(function (annot) {
                var annotHandler = _self.canAnswer(annot);
                if (annotHandler != null) {
                    annotHandler.onUpdatePosition(pageView, annot, visibleRect);
                }
                return true;
            });
          
        };

        this.onDocViewResize = function(){
            var canvasElem = _annotUIManager.getCanvasElement();
            var docView = _readerApp.getMainView().getDocView();
            var scrollApi = docView.getScrollApi();
            var jqPagesContainerDiv = $("#" + docView.getDocViewContainerID());
            if (canvasElem != null) {
                var docViewDimension = docView.getDocViewDimension();
                var left = 0, top = 0;
                if (scrollApi) {
                    left = scrollApi.getContentPositionX();
                    top = scrollApi.getContentPositionY();
                    docViewDimension.width -= scrollApi.getScrollBarWidth();
                    docViewDimension.height -= scrollApi.getScrollBarHeight();
                }
                canvasElem.width = docViewDimension.width;
                canvasElem.height = docViewDimension.height;
                $(canvasElem).css({ top: top, left: left });
            }
        };

        this.onPreDocViewResize = function(){
            var canvasElem = _annotUIManager.getCanvasElement();
            if (canvasElem != null) {
                canvasElem.height = 0;
                canvasElem.width = 0;
                $(canvasElem).css({ left: 0, top: 0 });
            }
            _pageAnnotNeedUpdateList.length = 0;
            var docView = _readerApp.getMainView().getDocView();
            var visiblePageRange = docView.getVisiblePageRange();
            for (var i = visiblePageRange.begin; i <= visiblePageRange.end; i++) {
                _pageAnnotNeedUpdateList.push(i);
            }
        };

        this.onDocViewScroll = function () {
            var docView = _readerApp.getMainView().getDocView();
            var scrollApi = docView.getScrollApi();
            var canvasElem = _annotUIManager.getCanvasElement();
            if (canvasElem != null) {
                var left = 0, top = 0;
                if (scrollApi) {
                    left = scrollApi.getContentPositionX();
                    top = scrollApi.getContentPositionY();
                }
                $(canvasElem).css({ top: top, left: left });
            }
            _self.onDraw();
        };

        this.createAnnotsHtmlContent = function(pageView){
          return _annotUIManager.createAnnotsHtmlContent(pageView);
        };

        this.getUIManager = function(){
            return _annotUIManager;
        };

        /**
         * Check whether an annotation is rendered with background image.
         * If the annotation is not rendered with background image, Web reader need to render it by html.
         * @param annot annotation to check.
         */
        this.isAnnotRenderWithBackgroundImage = function (annot) {
            //currently, Web reader for foxitcloud render all of annotation with background image,
            // so that we just return true right now.
            return false;
        };


        this.quadPointsToRectArray = function (quadPoints, annotType, pageMatrix) {
            if (quadPoints == null || quadPoints.length % 8 != 0)
                return null;
            var rectArray = [];
            for (var i = 0; i < quadPoints.length; i += 8) {
                var rect = null;
                if (annotType === WebPDF.PDFData.CommentAnnotType.COMMENTTYPE_HIGHLIGHT) {
                    rect = new PDFRect(quadPoints[i], quadPoints[i + 7], quadPoints[i + 2], quadPoints[i + 1]);
                    var transformRect = pageMatrix.TransFormRect(rect.left, rect.top, rect.right, rect.bottom);
                    rect.left = transformRect[0];
                    rect.top = transformRect[1];
                    rect.right = transformRect[2];
                    rect.bottom = transformRect[3];
                }
                else if (annotType === WebPDF.PDFData.CommentAnnotType.COMMENTTYPE_UNDERLINE) {
                    var width = Math.abs(quadPoints[i + 7] - quadPoints[i + 3]) / 8;
                    if (width < 1)
                        width = 1;
                    var fX1 = quadPoints[i] + (quadPoints[i + 4] - quadPoints[i]) / 8;
                    var fY1 = quadPoints[i + 5] + (quadPoints[i + 1] - quadPoints[i + 5]) / 8;
                    var fX2 = quadPoints[i + 2] + (quadPoints[i + 6] - quadPoints[i + 2]) / 8;
                    var fY2 = quadPoints[i + 7] + (quadPoints[i + 3] - quadPoints[i + 7]) / 8;
                    if (fX1 === fX2)
                        rect = new PDFRect(fX1 - width / 2, fY1, fX2 + width / 2, fY2);
                    else
                        rect = new PDFRect(fX1, fY1 + width / 2, fX2, fY2 - width / 2);
                    var transformRect = pageMatrix.TransFormRect(rect.left, rect.top, rect.right, rect.bottom);
                    rect.left = transformRect[0];
                    rect.top = transformRect[1];
                    rect.right = transformRect[2];
                    rect.bottom = transformRect[3];
                }

                RectUtils.normalize(rect);
                if (RectUtils.isEmpty(rect))
                    return null;
                rectArray.push(rect);
            }
            return rectArray;
        };
        
        function vectorLength(point) {
            return Math.sqrt(point.x * point.x + point.y * point.y);
        }
        
        function slopeAngle(point) {
        	var pointA = point;
        	var pointB = new PDFPoint(1.0, 0.0);
        	var dotProduct = pointA.x * pointB.x + pointA.y * pointB.y;
        	var cosine = dotProduct / (vectorLength(pointA) * vectorLength(pointB));
            return Math.acos(cosine);
//            return arcCosine(point, new PDFPoint(1.0, 0.0));
        } 

        this.drawAnnots = function (pageView, isRedraw, extraScale) {            
            if (!pageView)
                return;
            pageView.getPDFPage().enumAnnots(function (annot) {
                var annotHandler = _self.getAnnotHandlerByAnnot(annot);
                if (annotHandler != null) {
                    annotHandler.onDraw(pageView, annot, isRedraw, extraScale);
                }
                return true;
            });
        };

        this.showAnnots = function (pageView, bShow) {
            var jqAnnots = $("#" + _annotUIManager.getPageAnnotsContainerID(pageView));
            bShow ? jqAnnots.show() : jqAnnots.hide();
        };

        this.onDraw = function () {
            var ctx = _annotUIManager.clearCanvas();
            if (ctx == null) {
                return;
            }
            var canvas = _annotUIManager.getCanvasElement();
            if (canvas == null) {
                return false;
            }
            ctx = canvas.getContext("2d");
            var jqCanvas = $(canvas);
            var canvasOffset = jqCanvas.offset();
            _self.getMarkupAnnotHandler().onDraw(ctx, canvasOffset);
        };

        this.getCavansElement = function () {
            return document.getElementById(_annotCanvasID);
        };

        
        this.bindAnnotEvents = function () {

        };

        this.getAnnotVisibleRect = function (pageView, contentPanelOffset, contentPanelWidth, contentPaneHeight) {
            var pageWidth = pageView.getPageViewWidth(),
                pageHeight = pageView.getPageViewHeight(),
                pageIndex = pageView.getPageIndex();
            var jqPageContainer = $("#" + pageView.getPageViewContainerID());
            var scrollApi = pageView.getDocView().getScrollApi();
            var visibleWidth = contentPanelWidth;
            var visibleHeight = contentPaneHeight;
            var pageOffset = jqPageContainer.offset();
            if (scrollApi != null) {
                visibleHeight -= scrollApi.getScrollBarHeight();
                visibleWidth -= scrollApi.getScrollBarWidth();
            }

            var visibleRect = new PDFRect(0, 0, 0, 0);
            var bottomOverflow = pageOffset.top + pageHeight - (contentPanelOffset.top + visibleHeight);
            if (bottomOverflow < 0) {
                bottomOverflow = 0;
            }
            if ((pageOffset.top < contentPanelOffset.top)) {
                visibleRect.top = contentPanelOffset.top - pageOffset.top;
                visibleRect.bottom = visibleRect.top + pageHeight - (contentPanelOffset.top - pageOffset.top) - bottomOverflow;
            }
            else {
                visibleRect.top = 0;
                if (pageIndex === 0) {
                    visibleRect.top = contentPanelOffset.top - pageOffset.top;
                }
                visibleRect.bottom = pageHeight - bottomOverflow;
            }
            if (pageIndex === pageView.getDocView().getPageCount() - 1) {
                if (pageOffset.top + pageHeight < contentPanelOffset.top + visibleHeight) {
                    visibleRect.bottom += (contentPanelOffset.top + visibleHeight) - (pageOffset.top + pageHeight);
                }
            }
            var viewMode = pageView.getDocView().getViewMode();
            if (viewMode == WebPDF.PDFView.RD_BRMODE_CONTINUOUS_FACING) {
                var pagePanelWidth = (visibleWidth) / 2 - 11;
                if (pageIndex % 2 == 0) {
                    visibleRect.left = contentPanelOffset.left - pageOffset.left + 1;
                    var rightOverflow = pageOffset.left + pageWidth - (contentPanelOffset.left + visibleWidth);
                    visibleRect.right = pageWidth - 1;
                    if (rightOverflow > 0)
                        visibleRect.right -= rightOverflow;
                }
                else {
                    visibleRect.left = 0;
                    visibleRect.right = visibleRect.left + pagePanelWidth;
                    var rightOverflow = pageOffset.left + pageWidth - (contentPanelOffset.left + visibleWidth);
                    if (rightOverflow > 0) {
                        visibleRect.right = pageWidth - rightOverflow;
                    }
                }
            }
            else if (viewMode == WebPDF.PDFView.RD_BRMODE_CONTINUOUS) {
                visibleRect.left = contentPanelOffset.left - pageOffset.left + 1;
                visibleRect.right = visibleRect.left + visibleWidth;
            }
            return visibleRect;
        };
        this.getAnnotCavansDivID = function (pPageView, annotName) {
            return pPageView.getPageViewContainerID() + "_Annots_Canvas_" + annotName;
        };

        this.clearCanvas = function(){
            _annotUIManager.clearCanvas();
        };
        
        function _popupContextmenuHandler(event) {
            if (_readerApp.IsEditable()) {
                var nPageIndex = parseInt(event.currentTarget.getAttribute("page-index"));
                var annotName = event.currentTarget.getAttribute("annot-name");
                var pageView = _readerApp.getMainView().getDocView().getPageView(nPageIndex);
                var pPDFPage = pageView.getPDFPage();
                var annot = pPDFPage.getAnnotByName(annotName);
                if (annot != null) {
                    var pAnnotHandler = _self.CanAnswer(annot, true);
                    if (pAnnotHandler == null)
                        return true;

                    _self.clickOnAnnot(annot, pPageView, false, true);
                    $(".fwr_annot_selected").trigger("contextmenu.jeegoocontext", event);
                    return false;
                }
            }
            return true;
        };
        
        this.bindPopupContextmenuEvent = function () {
            $(".fwr_popup_annot").unbind("contextmenu", _popupContextmenuHandler).bind("contextmenu", _popupContextmenuHandler);
        }
    };

    return WebPDF.AnnotHandleManager;
});